/* Copyright (c) 2023-2023, LiWangQian<liwangqian@huawei.com> All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of
 *    conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
 *    of conditions and the following disclaimer in the documentation and/or other materials
 *    provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
 *    to endorse or promote products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include <catch2/catch.hpp>
#include <string_view>
#include "chi/lang/utils/text.h"

using namespace std::string_view_literals;
using namespace chi::lang;

auto short_string = "short"sv;
auto long_string  = "long string"sv;

TEST_CASE("test.chi.lang.utils.text.default_ctor")
{
    utils::text text;
    REQUIRE(text.data() == std::string(""));
    REQUIRE(text.shared() == false);
    REQUIRE(text.empty() == true);
    REQUIRE(text.size() == 0);
    REQUIRE(text.length() == 0);
}

TEST_CASE("test.chi.lang.utils.text.raw_ctor")
{
    utils::text text{short_string.data()};
    REQUIRE(text.data() == short_string);
    REQUIRE(text.shared() == false);
    REQUIRE(text.empty() == false);
    REQUIRE(text.size() == short_string.length());
    REQUIRE(text.length() == short_string.length());

    utils::text text2{long_string.data(), false};
    REQUIRE(text2.data() == long_string.data()); /* shared */
    REQUIRE(text2.shared() == true);
    REQUIRE(text2.empty() == false);
    REQUIRE(text2.size() == long_string.length());
    REQUIRE(text2.length() == long_string.length());

    utils::text text3{long_string.data()};
    REQUIRE(text3.data() == long_string);
    REQUIRE(text3.shared() == false);
    REQUIRE(text3.empty() == false);
    REQUIRE(text3.size() == long_string.length());
    REQUIRE(text3.length() == long_string.length());
}

TEST_CASE("test.chi.lang.utils.text.raw_len_ctor")
{
    utils::text text{short_string.data(), short_string.length()};
    REQUIRE(text.data() == short_string);
    REQUIRE(text.shared() == false);
    REQUIRE(text.empty() == false);
    REQUIRE(text.size() == short_string.length());
    REQUIRE(text.length() == short_string.length());

    utils::text text2{long_string.data(), false};
    REQUIRE(text2.data() == long_string.data()); /* shared */
    REQUIRE(text2.shared() == true);
    REQUIRE(text2.empty() == false);
    REQUIRE(text2.size() == long_string.length());
    REQUIRE(text2.length() == long_string.length());

    utils::text text3{long_string.data()};
    REQUIRE(text3.data() == long_string);
    REQUIRE(text3.shared() == false);
    REQUIRE(text3.empty() == false);
    REQUIRE(text3.size() == long_string.length());
    REQUIRE(text3.length() == long_string.length());
}

TEST_CASE("test.chi.lang.utils.text.str_ctor")
{
    auto str{std::string{"short"}};
    auto text1{utils::text{str}};
    REQUIRE(text1.data() == str);
    REQUIRE(text1.shared() == false);
    REQUIRE(text1.empty() == false);
    REQUIRE(text1.size() == str.size());

    auto text2{utils::text{short_string}};
    REQUIRE(text2.data() == short_string);
    REQUIRE(text2.shared() == false);
    REQUIRE(text2.empty() == false);
    REQUIRE(text2.size() == short_string.size());
}

TEST_CASE("test.chi.lang.utils.text.copy_ctor")
{
    auto str = std::string{"short"};
    auto text1{utils::text{str}};
    auto text2{text1};
    REQUIRE(text1.data() == str);
    REQUIRE(text2.data() == str);
    REQUIRE(!text1.shared());
    REQUIRE(!text2.shared());
}

TEST_CASE("test.chi.lang.utils.text.move_ctor")
{
    auto text1{utils::text{short_string}};
    auto text2{std::move(text1)};
    REQUIRE(text1.data() == ""sv);
    REQUIRE(text2.data() == short_string);
    REQUIRE(!text2.shared());
}

TEST_CASE("test.chi.lang.utils.text.copy_assign")
{
    auto text1 = utils::text{short_string};
    auto text2 = text1;
    utils::text text3 = std::string("abc");
    utils::text text4 = "abc"sv;
    utils::text text5 = "abc";
    utils::text text6 = "hello world";

    REQUIRE(text1.data() == short_string);
    REQUIRE(text2.data() == short_string);
    REQUIRE(text3.data() == "abc"sv);
    REQUIRE(text4.data() == "abc"sv);
    REQUIRE(text5.data() == "abc"sv);
    REQUIRE(text6.data() == "hello world"sv);
    REQUIRE(!text1.shared());
    REQUIRE(!text2.shared());
    REQUIRE(!text3.shared());
    REQUIRE(!text4.shared());
    REQUIRE(!text5.shared());
    REQUIRE(!text6.shared());
}

TEST_CASE("test.chi.lang.utils.text.move_assign")
{
    auto text1 = utils::text{short_string};
    auto text2 = std::move(text1);

    REQUIRE(text1.data() == ""sv);
    REQUIRE(text2.data() == short_string);
    REQUIRE(!text1.shared());
    REQUIRE(!text2.shared());
}

TEST_CASE("test.chi.lang.utils.text.compara")
{
    auto text1 = utils::text{"abc"};
    auto text2 = utils::text{"hello world"};

    REQUIRE(text1 != text2);
    REQUIRE(text1 == "abc");
    REQUIRE(text1 == "abc"sv);
    REQUIRE(text1 == std::string("abc"));
    REQUIRE("abc" == text1);
    REQUIRE("abc"sv == text1);
    REQUIRE(std::string("abc") == text1);
    REQUIRE(text1 < text2);
    REQUIRE(text2 > text1);
}

TEST_CASE("test.chi.lang.utils.text.reset")
{
    auto text1 = utils::text{"abc"};
    auto text2 = utils::text{"hello world"};
    text1.reset();
    text2.reset();
    REQUIRE(text1 == "");
    REQUIRE(text2 == "");
}

TEST_CASE("test.chi.lang.utils.text.to_string")
{
    auto text1 = utils::text{"abc"};
    auto text2 = utils::text{"hello world"};
    REQUIRE(text1.to_string() == "abc");
    REQUIRE(text2.to_string() == "hello world");
}
